﻿using System;
using System.Transactions;
using Hangfire;
using Hangfire.MySql;
using Hangfire.SqlServer;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace NiuX.Hangfire;

public static class HangfireExtensions
{
    public static void AddNiuXHangfireWithMySqlStorage(this IServiceCollection services, IConfiguration configuration, string connectionName = "HangfireConnection")
    {
        services.AddHangfire(x => x
         .SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
         .UseSimpleAssemblyNameTypeSerializer()
         .UseRecommendedSerializerSettings()
         .UseMySqlStorage(configuration, connectionName))
        .AddHangfireServer();
    }

    public static void AddNiuXHangfireWithSqlServerStorage(this IServiceCollection services, IConfiguration configuration, string connectionName = "HangfireConnection")
    {
        services.AddHangfire(x => x
         .SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
         .UseSimpleAssemblyNameTypeSerializer()
         .UseRecommendedSerializerSettings()
         .UseSqlServerStorage(configuration, connectionName))
        .AddHangfireServer();
    }

    private static IGlobalConfiguration UseMySqlStorage(this IGlobalConfiguration globalConfiguration, IConfiguration configuration, string connectionName = "HangfireConnection")
    {
        return globalConfiguration.UseStorage(new MySqlStorage(configuration.GetConnectionString(connectionName),
            new MySqlStorageOptions
            {
                TransactionIsolationLevel = IsolationLevel.ReadCommitted,
                QueuePollInterval = TimeSpan.FromSeconds(15),
                JobExpirationCheckInterval = TimeSpan.FromHours(1),
                CountersAggregateInterval = TimeSpan.FromMinutes(5),
                PrepareSchemaIfNecessary = true,
                DashboardJobListLimit = 50000,
                TransactionTimeout = TimeSpan.FromMinutes(1),
                TablesPrefix = "hangfire_"
            }));
    }

    private static IGlobalConfiguration UseSqlServerStorage(this IGlobalConfiguration globalConfiguration, IConfiguration configuration, string connectionName = "HangfireConnection")
    {
        return globalConfiguration.UseSqlServerStorage(configuration.GetConnectionString(connectionName), new SqlServerStorageOptions
        {
            CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
            SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
            QueuePollInterval = TimeSpan.Zero,
            UseRecommendedIsolationLevel = true,
            DisableGlobalLocks = true
        });
    }
}